package ar.edu.utn.frba.dds.tp.tests.ordenamientos;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import junit.framework.Assert;

import org.joda.time.LocalDate;
import org.joda.time.LocalTime;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;

import ar.edu.utn.frba.dds.tp.code.Asientos.AsientoDeVuelo;
import ar.edu.utn.frba.dds.tp.code.Asientos.ClaseAsiento;
import ar.edu.utn.frba.dds.tp.code.Asientos.EstadoAsiento;
import ar.edu.utn.frba.dds.tp.code.Asientos.UbicacionAsiento;
import ar.edu.utn.frba.dds.tp.code.adapter.AbstractConversor;
import ar.edu.utn.frba.dds.tp.code.ordenamientos.OrdenarPorPopularidad;
import ar.edu.utn.frba.dds.tp.code.ordenamientos.OrdenarPorPrecioAscendente;
import ar.edu.utn.frba.dds.tp.code.ordenamientos.OrdenarPorPrecioDescendente;
import ar.edu.utn.frba.dds.tp.code.ordenamientos.OrdenarPorTiempo;
import ar.edu.utn.frba.dds.tp.code.usuarios.Usuario;
import ar.edu.utn.frba.dds.tp.code.vuelos.Aerolinea;
import ar.edu.utn.frba.dds.tp.code.vuelos.Busqueda;
import ar.edu.utn.frba.dds.tp.code.vuelos.RegistroCompraAsientos;
import ar.edu.utn.frba.dds.tp.code.vuelos.Vuelo;

import com.google.common.collect.Ordering;

public class OrdenamientosTest {
	
	ArrayList<Vuelo> vuelos;
	
	Vuelo vueloVarios;
	Vuelo vueloClaseEjecutiva;
	Vuelo vueloUbicacionVentana;
	Vuelo vueloSinAsientosLibres;
	Vuelo vueloPrecio3000;
	
	
	OrdenarPorPrecioAscendente ascendente;
	OrdenarPorPrecioDescendente descendente;
	OrdenarPorPopularidad popularidad;
	OrdenarPorTiempo tiempo;
	
	@Mock Aerolinea aero;
	
	@Before
	public void setUp(){
		
		aero = new Aerolinea() {
			
			@Override
			public List<Vuelo> vuelosDisponibles(Busqueda busqueda) {
				//Mock
				return null;
			}
			
			@Override
			public void comprarAsiento(AsientoDeVuelo asiento, Usuario comprador) {
				//Mock
				
			}

			@Override
			public String getName() {
				// TODO Auto-generated method stub
				return null;
			}

			@Override
			public AbstractConversor getConversor() {
				// TODO Auto-generated method stub
				return null;
			}
		};
		
		vueloVarios = new Vuelo("6789", "BA", "LA", new LocalDate(2012, 10, 13).toDate() , new LocalDate(2012,10,14).toDate(), new LocalTime(17, 33), new LocalTime(17,34));
		vueloVarios.agregarAsiento(new AsientoDeVuelo(100, new BigDecimal(1000), ClaseAsiento.EJECUTIVA, UbicacionAsiento.PASILLO, EstadoAsiento.RESERVADO));
		vueloVarios.agregarAsiento(new AsientoDeVuelo(323, new BigDecimal(3000), ClaseAsiento.PRIMERA, UbicacionAsiento.CENTRO, EstadoAsiento.COMPRADO));
		vueloVarios.agregarAsiento(new AsientoDeVuelo(302,new BigDecimal(1250),ClaseAsiento.PRIMERA,UbicacionAsiento.PASILLO,EstadoAsiento.DISPONIBLE));
		vueloVarios.agregarAsiento(new AsientoDeVuelo(932, new BigDecimal(400), ClaseAsiento.EJECUTIVA, UbicacionAsiento.PASILLO, EstadoAsiento.DISPONIBLE));
		vueloVarios.agregarAsiento(new AsientoDeVuelo(423, new BigDecimal(1900),ClaseAsiento.PRIMERA,UbicacionAsiento.PASILLO,EstadoAsiento.DISPONIBLE));
		vueloVarios.setAerolinea(aero);
		
		vueloClaseEjecutiva = new Vuelo("1234", "BA", "LA", new LocalDate(2012,9,8).toDate(), new LocalDate(2012,9,10).toDate(), new LocalTime(12,00), new LocalTime(13,45));
		vueloClaseEjecutiva.agregarAsiento(new AsientoDeVuelo(100, new BigDecimal(1000), ClaseAsiento.EJECUTIVA, UbicacionAsiento.PASILLO, EstadoAsiento.DISPONIBLE));
		vueloClaseEjecutiva.setAerolinea(aero);
		
		vueloUbicacionVentana = new Vuelo("1234", "BA", "LA", new LocalDate(2012,8,23).toDate(), new LocalDate(2012,8,23).toDate(), new LocalTime(12,00), new LocalTime(16,00));
		vueloUbicacionVentana.agregarAsiento(new AsientoDeVuelo(100, new BigDecimal(1000), ClaseAsiento.TURISTA, UbicacionAsiento.VENTANA, EstadoAsiento.DISPONIBLE));
		vueloUbicacionVentana.setAerolinea(aero);
		
		vueloSinAsientosLibres = new Vuelo("1234", "BA", "LA", new LocalDate(2012,11,11).toDate(), new LocalDate(2012,11,13).toDate(), new LocalTime(7,55), new LocalTime(17,00));
		vueloSinAsientosLibres.agregarAsiento(new AsientoDeVuelo(100, new BigDecimal(1000), ClaseAsiento.TURISTA, UbicacionAsiento.PASILLO, EstadoAsiento.RESERVADO));
		vueloSinAsientosLibres.setAerolinea(aero);
		
		vueloPrecio3000 = new Vuelo("1234", "BA", "LA", new LocalDate(2012,12,12).toDate(), new LocalDate(2012,12,16).toDate(), new LocalTime(9,00), new LocalTime(9,00));
		vueloPrecio3000.agregarAsiento(new AsientoDeVuelo(100, new BigDecimal(3000), ClaseAsiento.TURISTA, UbicacionAsiento.PASILLO, EstadoAsiento.DISPONIBLE));
		vueloPrecio3000.setAerolinea(aero);
		
		this.ascendente = new OrdenarPorPrecioAscendente();
		this.descendente = new OrdenarPorPrecioDescendente();
		this.tiempo = new OrdenarPorTiempo();
		this.popularidad = new OrdenarPorPopularidad();
		
		vuelos = new ArrayList<Vuelo>();
		vuelos.add(vueloClaseEjecutiva);
		vuelos.add(vueloUbicacionVentana);
		vuelos.add(vueloSinAsientosLibres);
		vuelos.add(vueloPrecio3000);
		vuelos.add(vueloVarios);
		
		
		
		
		RegistroCompraAsientos.getInstance().setValue(aero , vueloVarios, 10);
		RegistroCompraAsientos.getInstance().setValue(aero, vueloClaseEjecutiva, 8);
		RegistroCompraAsientos.getInstance().setValue(aero, vueloUbicacionVentana, 13);
		RegistroCompraAsientos.getInstance().setValue(aero, vueloSinAsientosLibres, 0);
		RegistroCompraAsientos.getInstance().setValue(aero, vueloPrecio3000, 3);
	}
	
	@Test
	public void testOrdenPorTiempoDeVuelo(){
		
		Ordering<Vuelo> ordenMenorTiempo = new Ordering<Vuelo>() {
			
			@Override
			public int compare(Vuelo unVuelo, Vuelo otroVuelo) {
				return unVuelo.tiempoDeVuelo().compareTo(otroVuelo.tiempoDeVuelo());
			}
		};
		
		Assert.assertTrue(ordenMenorTiempo.isOrdered(this.tiempo.ordenarVuelos(this.vuelos)));
	}
	
	@Test
	public void testOrdenarPrecioAscendente(){
		
		Ordering<AsientoDeVuelo> ordenPrecioAscendenteAsientos = new Ordering<AsientoDeVuelo>() {
			
			@Override
			public int compare(AsientoDeVuelo unAsiento, AsientoDeVuelo otroAsiento) {
				return unAsiento.getPrecio().compareTo(otroAsiento.getPrecio());
			}
		};
		
		ArrayList<Vuelo> vueloAOrdenar = new ArrayList<Vuelo>();
		vueloAOrdenar.add(this.vueloVarios);
		
		Assert.assertTrue(ordenPrecioAscendenteAsientos.isOrdered(this.ascendente.ordenarVuelos(vueloAOrdenar).get(0).getAsientos()));
		
	}
	
	@Test
	public void testOrdenarPrecioDescendente(){
		
		Ordering<AsientoDeVuelo> ordenPrecioDescendenteAsientos = new Ordering<AsientoDeVuelo>() {
			
			@Override
			public int compare(AsientoDeVuelo unAsiento, AsientoDeVuelo otroAsiento) {
				return otroAsiento.getPrecio().compareTo(unAsiento.getPrecio());
			}
		};
		
		ArrayList<Vuelo> vueloAOrdenar = new ArrayList<Vuelo>();
		vueloAOrdenar.add(this.vueloVarios);
		
		Assert.assertTrue(ordenPrecioDescendenteAsientos.isOrdered(this.descendente.ordenarVuelos(vueloAOrdenar).get(0).getAsientos()));
		
	}
	
	@Test
	public void testOrdenadosPorPopularidad(){
		
		Ordering<Vuelo> ordenPopularidad = new Ordering<Vuelo>() {
			
			@Override
			public int compare(Vuelo unVuelo , Vuelo otroVuelo) {
				return otroVuelo.getCantidadAsientosComprados().compareTo(unVuelo.getCantidadAsientosComprados());
			}
		};
		
		Assert.assertTrue(ordenPopularidad.isOrdered(this.popularidad.ordenarVuelos(this.vuelos)));
		
	}
	
	@After
	public void tearDown(){
		RegistroCompraAsientos.getInstance().deleteValue(aero , vueloVarios);
		RegistroCompraAsientos.getInstance().deleteValue(aero, vueloClaseEjecutiva);
		RegistroCompraAsientos.getInstance().deleteValue(aero, vueloUbicacionVentana);
		RegistroCompraAsientos.getInstance().deleteValue(aero, vueloSinAsientosLibres);
		RegistroCompraAsientos.getInstance().deleteValue(aero, vueloPrecio3000);
	}
	
	
	
	
}
